<template>
	<TreeSelect v-bind="bindValue" @change="handleChange" placeholder="请选择">
		<template #[item]="data" v-for="item in Object.keys($slots)">
			<slot :name="item" v-bind="data || {}"></slot>
		</template>
		<template #suffixIcon v-if="loading">
			<LoadingOutlined spin />
		</template>
	</TreeSelect>
</template>
<script lang="ts">
import { TreeSelect } from 'ant-design-vue';
import { computed, defineComponent, onMounted, PropType, ref, unref, watch } from 'vue';
import { isFunction, isArray } from '@/utils/is';
import { get } from 'lodash-es';
import { LoadingOutlined } from '@ant-design/icons-vue';

export default defineComponent({
	name: 'DeptPersonTreeSelect',
	inheritAttrs: false,
	components: { TreeSelect, LoadingOutlined },
	props: {
		api: { type: Function as PropType<(arg?: Recordable) => Promise<Recordable>> },
		params: { type: Object },
		// immediate: { type: Boolean, default: true },
		resultField: { type: String as PropType<string>, default: '' },
	},
	emits: ['change', 'options-change', 'label-change'],
	setup(props, { attrs, emit }) {
		const treeData = ref<Recordable[]>([]);
		const isFirstLoaded = ref<Boolean>(false);
		const loading = ref(false);

		const bindValue = computed(() => ({
			...(props.api ? { treeData: unref(treeData) } : {}),
			...attrs,
			treeNodeFilterProp: 'title',
			dropdownStyle: { maxHeight: '400px', overflow: 'auto' },
			showCheckedStrategy: TreeSelect.SHOW_CHILD,
		}));

		function handleChange(...args: any[]) {
			emit('label-change', args[1]);
			emit('change', ...args);
		}

		watch(
			() => props.params,
			() => {
				!unref(isFirstLoaded) && fetch();
			},
			{ deep: true },
		);

		onMounted(() => {
			fetch();
		});

		async function fetch() {
			const { api } = props;
			if (!api || !isFunction(api)) return;
			loading.value = true;
			treeData.value = [];
			let result;
			try {
				result = await api(props.params);
			} catch (e) {
				console.error(e);
			}

			loading.value = false;
			if (!result) return;
			if (!isArray(result)) {
				result = get(result, props.resultField);
			}
			generateTreeNode(result);

			treeData.value = (result as Recordable[]) || [];
			isFirstLoaded.value = true;
			emit('options-change', treeData.value);
		}

		// 人员必须是最后一级
		function generateTreeNode(tree: Recordable[]) {
			tree.map(T => {
				T.key = T.deptId;
				T.value = T.deptId;
				T.selectable = false;
				T.title = T.name;
				if (T.principalList?.length) {
					T.children = [];
					T.principalList.map((P: Recordable) => {
						P.selectable = true;
						P.key = P.userId;
						P.value = P.userId;
						P.title = P.userName;
						T.children.push(P);
					});
					return;
				}
				T.children && T.children.length && generateTreeNode(T.children);
			});
			return tree;
		}

		return {
			handleChange,
			bindValue,
			loading,
		};
	},
});
</script>
